import re

import requests
from manager.lock_manager import LockManager
from model.park_spider import ParkSpider
from model.park_platform import ParkPlatform
from model.car_number import CarNumber
from model.result import Result
from model.error import ParkSpiderError, ParkSpiderErrorCode, TokenExpireError

import dateutil.parser as dateutil

from urllib import parse
import common.http as http
import spider_config
import json
from datetime import datetime
import time
from common.logger import logger
import base64
import hashlib


class YmiotParkSpider(ParkSpider):
    def platform(self) -> ParkPlatform:
        return ParkPlatform(spider_config.ymiot_park_id)

    def build_token(self, carNumber: CarNumber, sign: str):
        token = parse.quote(str(carNumber)) + sign + "jiamisfmtoken-ymiot.net"
        # 对sign进行base64编码
        token = base64.b64encode(token.encode("utf-8"))
        # 对sign进行md5加密
        token = hashlib.md5(token).hexdigest()
        # 对sign进行反转
        token = token[::-1]
        # 对sign进行大写
        token = token.upper() + sign
        return token

    def calc_price(self, hour: int):
        """蓝牌车4小时内4元，4-12小时内8元，12-24小时内12元。"""

        if hour <= 4:
            return 4
        elif hour <= 12:
            return 8
        elif hour <= 24:
            return 12
        else:
            return int(hour / 24) * 12 + self.calc_price(hour % 24)

    def query(self, carNumber: CarNumber) -> Result:
        account = self.getAccount()

        if not account:
            raise ParkSpiderError(ParkSpiderErrorCode.YmiotAccountEmpty)

        state = account["state"]
        userNo = account["userNo"]
        sign = account["sign"]

        # 将中文改为%u开头的16进制
        carNo = str(carNumber).encode("unicode-escape").decode("utf-8")
        carNo = carNo.upper().replace("\\U", "%u")

        result = Result()
        result.platform = self.platform()
        result.car_number = carNumber

        token = self.build_token(carNumber, sign)

        url = "http://wx.ymiot.net/SCPay/SearchsOrderByCarNo?parkKey="

        headers = {
            "Host": "wx.ymiot.net",
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "X-Requested-With": "XMLHttpRequest",
            "Accept-Language": "zh-CN,zh-Hans;q=0.9",
            "Accept-Encoding": "gzip, deflate",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Origin": "http://wx.ymiot.net",
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.33(0x18002126) NetType/WIFI Language/en",
            "Referer": "http://wx.ymiot.net/SCPay/Index/?linktype=1&parkKey=&t=230315222757161",
            "Cookie": f"carNo={carNo};state={state}; userNo={userNo}",
        }

        data = {
            "carNo": str(carNumber),
            "token": token,
            "carTypeChange": 1,
        }

        # 将data里的数据用&拼接成字符串
        data = parse.urlencode(data)

        with LockManager.instance().get(self.platform().id, userNo):
            rsp = http.post(
                url,
                headers=headers,
                data=data,
                proxies=self.getProxy(),
                timeout=self.getTimeout(),
            )

            logger.debug(f"云联查询 {carNumber} 结果:{rsp.text}")

            if rsp.status_code != 200:
                raise requests.exceptions.ProxyError(f"云联反爬: {rsp.status_code}")

            rspJson = json.loads(rsp.text)

            try:
                if not rspJson["success"] and "不允许访问" in rspJson["message"]:
                    pass
            except Exception as e:
                logger.error(rspJson)
                return result

            if not rspJson["success"] and "不允许访问" in rspJson["message"]:
                raise TokenExpireError(userNo)
            
            if not rspJson["success"]:
                return result
                
            pay_url = "http://wx.ymiot.net" + rspJson["data"]

            rsp = http.get(
                pay_url,
                headers=headers,
                # proxies=self.getProxy(),
                timeout=self.getTimeout(),
            )

            if rsp.status_code != 200:
                raise requests.exceptions.ProxyError(f"云联反爬: {rsp.status_code}")

            # <dl><dd>停车地点</dd><dd class="parkname">深圳市富联二区停车场 </dd></dl>
            # <dl><dd>入场时间</dd><dd>2023/03/03 17:59:09 </dd></dl>
            # <dl><dd>入场车道</dd><dd>入口车道 </dd></dl>
            # <dl><dd>停车时长</dd><dd id="tctime">0天0小时0分0秒</dd></dl>
            # <dl><dd>应缴金额</dd><dd id="yjmoney">￥0.00</dd></dl>
            # <dl><dd>实缴金额</dd><dd id="sjmoney">￥0.00</dd></dl>

            r_park = re.search(
                r'<dl><dd>停车地点</dd><dd class="parkname">(.*?)<', rsp.text
            )
            r_time = re.search(r"<dl><dd>入场时间</dd><dd>(.*?)<", rsp.text)
            r_price = re.search(r'<dl><dd>应缴金额</dd><dd id="yjmoney">￥(.*?)<', rsp.text)

            try:
                result.success = True
                result.park_name = r_park.group(1)
                result.enter_time = dateutil.parse(r_time.group(1))
                result.platform = self.platform()
                result.price = float(r_price.group(1))
            except Exception as e:
                result.success = False
                logger.error(f"云联查询 {carNumber} 解析异常:{repr(e)}")

            # if result.enter_time:
            #     hour = int((datetime.now() - result.enter_time).total_seconds() / 3600)
            #     result.price = self.calc_price(hour)

            return result
